#include "stdio.h"
#include "data_proc.h"
#include <string.h>
#include <sys/time.h>

//#include "lecpa.h"

void parse_frame(unsigned char * buffIn, unsigned int len, op_st* opResult)
{
	if(buffIn==NULL || len<=0)
	{
		return;
	}
	opResult->ele_num = GET_ELE_NUM(buffIn[INDEX_OPCODE]);
	opResult->opcode = GET_ELE_OP(buffIn[INDEX_OPCODE]);
	
	if((opResult->opcode == MOVE)&&(len>2))
	{
		unsigned int i, temp;
		opResult->un_param.param_move.direct = (int)buffIn[INDEX_DIR];
		opResult->un_param.param_move.num_pulse = 0;
		temp = 0;
		for(i=0;i<LEN_NUM_PULSE;i++)
		{
			temp = 0x000000ff&buffIn[INDEX_DIR+1 + i];
			temp = (temp<<(8*i));
			opResult->un_param.param_move.num_pulse +=  temp;
		} 
	}	
}
/*
void act(op_st* opIn)
{
	int actCode = opIn->opcode;
	switch(actCode)
	{
		case RET_BACK:
			ret_back(opIn->ele_num);
			break;
		case MOVE:
			move(opIn->ele_num, opIn->un_param.param_move.direct, opIn->un_param.param_move.num_pulse);
			break;
		case STOP:
			stop(opIn->ele_num);
			break;
    default:
      break;			
	}
}*/

typedef unsigned short uint16_t;
typedef unsigned char uint8_t;

int stopFlag = 0;

uint16_t adjustOffset(int chanNum,uint8_t currAbove, uint16_t curOffset)
{

	//the current value is bigger than 0x8000

	uint16_t offsetToSet = curOffset;
	uint8_t posValue = ((curOffset & 0x3f00) >> 8);
	uint8_t negValue = curOffset & 0x003f;

	uint16_t totalValue = negValue + (posValue << 6);
	uint16_t tmpMask = curOffset & 0x8080;

	if (stopFlag)
	{
		return -1;
	}

	if (currAbove)
	{
		if ((curOffset & 0x8080) == 0x0080)
		{
			if (totalValue < 0x0fff)
			{
				totalValue++;
				if (negValue < 0x3f)
				{
					negValue++;
				}
				else if (posValue < 0x3f)
				{
					posValue++;
				}
			}
			else
			{
				//achieved the max neg offset; the calibration is not available;

				printf("achived the max neg offset\n");
				stopFlag = 1;
			}
		}
		else
		{
			if ((curOffset & 0x8080) == 0x0000)
			{
				if (negValue > 0)
				{
					negValue--;
				}
				else if (posValue < 0x3f)
				{
					posValue++;
				}
				else
				{

					offsetToSet |= 0x0080;
					//negValue = 1;
				}
			}
			else if ((curOffset & 0x8080) == 0x8000)
			{
				if (negValue > 0)
				{
					negValue--;
				}
				else if (posValue > 0)
				{
					posValue--;
				}
				else
				{
					offsetToSet |= 0x0080;
					//negValue = 1;
				}
			}
			else if ((curOffset & 0x8080) == 0x8080)
			{
				if (negValue < 0x3f)
				{
					negValue++;
				}
				else if (posValue > 0)
				{
					posValue--;
				}
				else
				{
					offsetToSet &= 0x0080;
					//posValue = 1;
				}
			}
		}
	}
	else
	{
		switch (tmpMask)
		{
		case 0x8000:
			if (totalValue < 0x0fff)
			{
				totalValue++;
				if (negValue < 0x3f)
				{
					negValue++;
				}
				else if (posValue < 0x3f)
				{
					posValue++;
				}
			}
			else
			{

				//achieved the max post offset; the calibration is not available;
				printf("achived the max pos offset\n");
				stopFlag = 1;
			}
			break;
		case 0x8080:
			if (negValue > 0)
			{
				negValue--;
			}
			else if (posValue < 0x3f)
			{
				posValue++;
			}
			else
			{
				offsetToSet &= 0x8000;
				//negValue = 1;
			}
			break;

		case 0x0080:
			if (negValue > 0)
			{
				negValue--;
			}
			else if (posValue > 0)
			{
				posValue--;
			}
			else
			{
				offsetToSet &= 0x8000;
				//negValue = 1;
			}
			break;

		case 0x0000:
			if (negValue < 0x3f)
			{
				negValue++;
			}
			else if (posValue > 0x00)
			{
				posValue--;
			}
			else
			{
				offsetToSet |= 0x8000;
				//posValue = 1;
			}
			break;
		default:
			break;

		}

	}

	offsetToSet &= 0x8080;
	offsetToSet += (negValue & 0x3f);
	offsetToSet += ((posValue & 0x3f) << 8);
	//printf("posValue:%d,negValue:%d\n",posValue,negValue);

	return offsetToSet;
}

#define MAX_DATA_BUFF 1024

class CDataFile
{
private:
	FILE * m_fd;
	char * m_buff;
	int m_currBufSize;
	int dataNum;	
public:
    CDataFile(const char* fileName,const int buffSize);
	virtual ~CDataFile();
    int addToDataBuff(const char* data,int len);
    int writeToFile(void);

	int isValid(void);
	
};

CDataFile::CDataFile(const char* fileName,const int buffSize=MAX_DATA_BUFF)
{
    if(fileName==NULL)
    {
        m_fd = NULL;
        return;
    }

    dataNum = 0;

    char fileNameStr[256];
    const char * ptrName = NULL;
    memset(fileNameStr,256,0);

    struct timeval tv;
    gettimeofday(&tv,NULL);

    ptrName = strchr(fileName,'.');

    if(ptrName)
    {
        int len = ptrName-fileName;
        memcpy(fileNameStr,fileName,len);

        len += sprintf(fileNameStr+len,"_%d",tv.tv_sec);
        len += sprintf(fileNameStr+len,"%s",ptrName);
    }
    else
    {
        int len = strlen(fileName);
        memcpy(fileNameStr,fileName,len);

        len += sprintf(fileNameStr+len,"_%d",tv.tv_sec);
    }

    m_fd = fopen(fileNameStr,"w");
    if(m_fd==NULL)
    {
        printf("openfile failed\n");
        return;
    }
    m_buff = new char[buffSize]; 

	memset(m_buff,0,buffSize);

    dataNum = 0;
    m_currBufSize = 0;   
}

CDataFile::~CDataFile()
{
    if(m_currBufSize)
    {
        if(this->isValid())
        {
            writeToFile();
        }

        m_currBufSize = 0;             

    }

    if(m_fd)
    {
        fclose(m_fd);
        m_fd = NULL;
    }

    if(m_buff)
    {
        delete [] m_buff;
        m_buff = NULL;
    }

    dataNum = 0;

}
int CDataFile::addToDataBuff(const char* data,int len)
{
    if(!this->isValid())
    {
        return -1;
    }
    

    if((len+m_currBufSize+2) < MAX_DATA_BUFF)
    {
		printf("data is:%s,m_currBufSize:%d\n",data,m_currBufSize);
        memcpy(m_buff+m_currBufSize,data,len);
		for(int i=0;i<len;i++)
		{
			printf("data[%d]:%02x,m_buff[%d]:%02x\n",i,data[i],i,m_buff[i]);
		}
        m_currBufSize += len;
    }
    else
    {
        writeToFile();
        memcpy(m_buff,data,len);
        m_currBufSize = len;
    }

    dataNum++;
    if(dataNum>=50)
    {
       m_buff[m_currBufSize++] = '\r';
       m_buff[m_currBufSize++] = '\n';
       dataNum=0; 
    }


}
int CDataFile::writeToFile(void)
{
    if(!m_fd)
    {
        return -1;
    }
    printf("data write to file:%s,size:%d\n",m_buff,m_currBufSize);
    fwrite(m_buff,m_currBufSize,1,m_fd);
    fflush(m_fd);
    m_currBufSize = 0;

}

int CDataFile::isValid(void)
{
    if(m_fd&&m_buff)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

extern int g_exitFlag;

CDataFile * g_fileCapData = 0;

int main(int argc, char *argv[])
{
  unsigned char one_frame[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  op_st test_result;
  unsigned int numPulse = 10000;
  memset(&test_result,0,sizeof(op_st));
  printf("RET_BACK[%d],MOVE[%d],STOP[%d]\n",RET_BACK,MOVE,STOP);  
  parse_frame(one_frame,8,&test_result);

  printf("test1,ele_num is %d,actCode is %d\n",test_result.ele_num,test_result.opcode);


  one_frame[0] = 0x01;
  one_frame[1] = 0x01;
  one_frame[2] = numPulse&0x000000ff;
  one_frame[3] = ((numPulse&0x0000ff00) >>8);
  one_frame[4] = ((numPulse&0x00ff0000) >>16);
  one_frame[5] = ((numPulse&0xff000000) >>24);

  memset(&test_result,6,sizeof(op_st));
  parse_frame(one_frame,8,&test_result);
  printf("test2,ele_num is %d,actCode is %d\n",test_result.ele_num,test_result.opcode);
  
  if(test_result.opcode == MOVE)
  {
	  printf("move, dir[%d],pulsNum[%d]\n",test_result.un_param.param_move.direct,
	  test_result.un_param.param_move.num_pulse);
  }

  one_frame[0] = 0x02;
  one_frame[1] = 0x00;
  one_frame[2] = 0x00;
  one_frame[3] = 0x00;
  one_frame[4] = 0x00;
  one_frame[5] = 0x00;

  memset(&test_result,0,sizeof(op_st));
  parse_frame(one_frame,8,&test_result);
  printf("test3,ele_num is %d,actCode is %d\n",test_result.ele_num,test_result.opcode);



  uint16_t offset = 0x0084;
  unsigned char above = 0;
  char strBuff[1024];
  FILE *fp = fopen("calibrateTest.txt","wr");
  int totalLen = 0; 
  memset(strBuff,0,1024);
  if(fp==NULL)
  {
	  printf("open file failed\n");
	  return 1;
  }
 
   totalLen += sprintf(strBuff+totalLen,"%04x,",offset);
   int i=0;
   int j=0;
   while(!stopFlag)
   {
	   
       offset = adjustOffset(0,above,offset);
       totalLen += sprintf(strBuff+totalLen,"%04x,",offset);

	   i++;
	   j++;
	   if(j>=4096)
	   {
		   break;
	   }
	   if(i>=50)
	   {
		   totalLen += sprintf(strBuff+totalLen,"\r\n");
		   i=0;
	   }

	   if(totalLen>=900)
	   {
		    fwrite(strBuff,totalLen,1,fp);
            totalLen = 0; 
            memset(strBuff,0,1024);
	   }
		
   }

   if(totalLen>0)
   {
	    fwrite(strBuff,totalLen,1,fp);
        totalLen = 0; 
        memset(strBuff,0,1024);
   }

   fclose(fp); 

   g_fileCapData =  new CDataFile("cap_data.txt",2048);

   unsigned short testData = 0x7fff;

   char buffTemp[32];

   sprintf(buffTemp,"%d\t",testData);

   printf("%s\n",buffTemp);

   g_fileCapData->addToDataBuff(buffTemp,strlen(buffTemp));

   delete g_fileCapData;
   g_fileCapData = NULL;

}
